/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Cryptographic Key Factory Class
 *      Provides a static class for generating key and initialization vector 
 * values for cryptographic operations.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.Security.Cryptography;

namespace Adaptive.Foundation.Security
{
    /// <summary>
    /// Provides a static class for generating key and initialization vector 
    /// values for cryptographic operations.
    /// </summary>
    public static class CryptoKeyFactory
    {
        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Generates an encryption key based on the supplied algorithm value.
        /// </summary>
        /// <param name="algorithm">
        /// A <see cref="CryptographicAlgorithm"/> enumerated value indicating the 
        /// algorithm to generate a key value for.
        /// </param>
        /// <returns>
        /// A byte array containing the new key value.
        /// </returns>
        public static byte[] GenerateKey(CryptographicAlgorithm algorithm)
        {
            byte[] returnValue = null;              //Return value.

            switch (algorithm)
            {
                case CryptographicAlgorithm.MultiAes:
                case CryptographicAlgorithm.Aes:
                    returnValue = GenerateAesKey();
                    break;

                case CryptographicAlgorithm.Des:
                    returnValue = GenerateDesKey();
                    break;

                case CryptographicAlgorithm.Rc2:
                    returnValue = GenerateRc2Key();
                    break;

                case CryptographicAlgorithm.TripleDes:
                    returnValue = GenerateTripleDesKey();
                    break;

            }
            return returnValue;
        }
        /// <summary>
        /// Generates an initialization vector based on the supplied algorithm value.
        /// </summary>
        /// <param name="algorithm">
        /// A <see cref="CryptographicAlgorithm"/> enumerated value indicating the 
        /// algorithm to generate a key value for.
        /// </param>
        /// <returns>
        /// A byte array containing the new IV value.
        /// </returns>
        public static byte[] GenerateIV(CryptographicAlgorithm algorithm)
        {
            byte[] returnValue = null;              //Return value.

            switch (algorithm)
            {
                case CryptographicAlgorithm.MultiAes:
                case CryptographicAlgorithm.Aes:
                    returnValue = GenerateAesIV();
                    break;

                case CryptographicAlgorithm.Des:
                    returnValue = GenerateDesIV();
                    break;

                case CryptographicAlgorithm.Rc2:
                    returnValue = GenerateRc2IV();
                    break;

                case CryptographicAlgorithm.TripleDes:
                    returnValue = GenerateTripleDesIV();
                    break;

            }
            return returnValue;
        }
        /// <summary>
        /// Generates an encryption key specifically for the AES algorithm.
        /// </summary>
        /// <returns>
        /// A byte array containing the new key value.
        /// </returns>
        public static byte[] GenerateAesKey()
        {
            RijndaelManaged aes = null;
            byte[] returnValue = null;

            aes = new RijndaelManaged();
            aes.GenerateKey();
            returnValue = aes.Key;
            aes.Clear();
            aes = null;
            return returnValue;
        }
        /// <summary>
        /// Generates an initialization vector specifically for the AES algorithm.
        /// </summary>
        /// <returns>
        /// A byte array containing the new IV value.
        /// </returns>
        public static byte[] GenerateAesIV()
        {
            RijndaelManaged aes = null;
            byte[] returnValue = null;

            aes = new RijndaelManaged();
            aes.GenerateIV();
            returnValue = aes.IV;
            aes.Clear();
            aes = null;
            return returnValue;
        }
        /// <summary>
        /// Generates an encryption key specifically for the DES algorithm.
        /// </summary>
        /// <returns>
        /// A byte array containing the new key value.
        /// </returns>
        public static byte[] GenerateDesKey()
        {
            DESCryptoServiceProvider des = null;
            byte[] returnValue = null;

            des = new DESCryptoServiceProvider();
            des.GenerateKey();
            returnValue = des.Key;
            des.Clear();
            des = null;
            return returnValue;
        }
        /// <summary>
        /// Generates an initialization vector specifically for the DES algorithm.
        /// </summary>
        /// <returns>
        /// A byte array containing the new IV value.
        /// </returns>
        public static byte[] GenerateDesIV()
        {
            DESCryptoServiceProvider des = null;
            byte[] returnValue = null;

            des = new DESCryptoServiceProvider();
            des.GenerateIV();
            returnValue = des.IV;
            des.Clear();
            des = null;
            return returnValue;
        }
        /// <summary>
        /// Generates an encryption key specifically for the Triple-DES algorithm.
        /// </summary>
        /// <returns>
        /// A byte array containing the new key value.
        /// </returns>
        public static byte[] GenerateTripleDesKey()
        {
            TripleDESCryptoServiceProvider tripleDes = null;
            byte[] returnValue = null;

            tripleDes = new TripleDESCryptoServiceProvider();
            tripleDes.GenerateKey();
            returnValue = tripleDes.Key;
            tripleDes.Clear();
            tripleDes = null;
            return returnValue;
        }
        /// <summary>
        /// Generates an initialization vector specifically for the Triple-DES algorithm.
        /// </summary>
        /// <returns>
        /// A byte array containing the new IV value.
        /// </returns>
        public static byte[] GenerateTripleDesIV()
        {
            TripleDESCryptoServiceProvider tripleDes = null;
            byte[] returnValue = null;

            tripleDes = new TripleDESCryptoServiceProvider();
            tripleDes.GenerateIV();
            returnValue = tripleDes.IV;
            tripleDes.Clear();
            tripleDes = null;
            return returnValue;
        }
        /// <summary>
        /// Generates an encryption key specifically for the RC2 algorithm.
        /// </summary>
        /// <returns>
        /// A byte array containing the new key value.
        /// </returns>
        public static byte[] GenerateRc2Key()
        {
            RC2CryptoServiceProvider rc2 = null;
            byte[] returnValue = null;

            rc2 = new RC2CryptoServiceProvider();
            rc2.GenerateKey();
            returnValue = rc2.Key;
            rc2.Clear();
            rc2 = null;
            return returnValue;
        }
        /// <summary>
        /// Generates an initialization vector specifically for the RC2 algorithm.
        /// </summary>
        /// <returns>
        /// A byte array containing the new IV value.
        /// </returns>
        public static byte[] GenerateRc2IV()
        {
            RC2CryptoServiceProvider rc2 = null;
            byte[] returnValue = null;

            rc2 = new RC2CryptoServiceProvider();
            rc2.GenerateIV();
            returnValue = rc2.IV;
            rc2.Clear();
            rc2 = null;
            return returnValue;
        }
        /// <summary>
        /// Generates a public encryption key specifically for the RSA algorithm.
        /// </summary>
        /// <returns>
        /// A byte array containing the new key value.
        /// </returns>
        public static byte[] GenerateRsaPublicKey()
        {
            RSACryptoServiceProvider rsa = null;
            RSAParameters rsaParams;
            byte[] returnValue = null;

            rsa = new RSACryptoServiceProvider(1024);
            rsa.PersistKeyInCsp = true;

            rsaParams = rsa.ExportParameters(false);
            returnValue = new byte[rsaParams.Modulus.Length];

            Array.Copy(rsaParams.Modulus, 0, returnValue, 0, rsaParams.Modulus.Length);

            rsa.Clear();
            rsa = null;
            return returnValue;
        }
        /// <summary>
        /// Converts the specified password value to an AES IV value.
        /// </summary>
        /// <param name="passwordText">
        /// The text to be transformed.
        /// </param>
        /// <returns>
        /// A byte array containing the key.
        /// </returns>
        public static byte[] PasswordToAesIV(string passwordText)
        {
            Rfc2898DeriveBytes deriver = null;      //Password to key translator.
            byte[] returnValue = null;              //Return value.

            deriver = new Rfc2898DeriveBytes(passwordText, new byte[8] { 0, 0, 0, 0, 1, 1, 1, 1 });
            returnValue = deriver.GetBytes(16);
            deriver.Reset();

            return returnValue;
        }
        /// <summary>
        /// Converts the specified password value to an AES IV value.
        /// </summary>
        /// <param name="passwordText">
        /// The text to be transformed.
        /// </param>
        /// <returns>
        /// A byte array containing the key.
        /// </returns>
        public static byte[] PasswordToAesKey(string passwordText)
        {
            Rfc2898DeriveBytes deriver = null;      //Password to key translator.
            byte[] returnValue = null;              //Return value.

            deriver = new Rfc2898DeriveBytes(passwordText, new byte[8] { 0, 0, 0, 0, 1, 1, 1, 1 });
            returnValue = deriver.GetBytes(32);
            deriver.Reset();
            
            return returnValue;
        }
        /// <summary>
        /// Creates a derived key set from the supplied password value.
        /// </summary>
        /// <param name="passwordText">The text of the password.</param>
        /// <param name="size">The number of new items to create.</param>
        /// <returns>
        /// A <see cref="DerivedKeySetCollection"/> containing the derived key set.
        /// </returns>
        public static DerivedKeySetCollection CreateKeySetForPassword(string passwordText, int size)
        {
            DerivedKeySetCollection returnValue = null;
            byte[] startKey = null;
            byte[] startIV = null;

            startKey = PasswordToAesKey(passwordText);
            startIV = PasswordToAesIV(passwordText);

            returnValue = KeyVariantFactory.CreateAesDerivedKeySet(startKey, startIV, size);
            return returnValue;
        }
        #endregion
    }
}